package com.gitee.tianchaohongyu.jdcl.support;

import com.gitee.tianchaohongyu.jdcl.core.CleanException;
import com.gitee.tianchaohongyu.jdcl.core.Cleaner;
import com.gitee.tianchaohongyu.jdcl.core.CleanerAnnotation;
import com.gitee.tianchaohongyu.jdcl.util.ReflectUtils;

import javax.validation.constraints.NotNull;
import java.lang.annotation.*;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 四舍五入，只处理Float、Double、BigDecimal，其他类型抛出异常。
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.METHOD})
@CleanerAnnotation(Round.TempCleaner.class)
public @interface Round {

  /** 保留小数位数，默认两位 */
  int value() default 2;

  /** 舍入模式，默认四舍五入 */
  RoundingMode roundingMode() default RoundingMode.HALF_UP;

  /**
   * 清洗器实现
   */
  class TempCleaner implements Cleaner<Number, Round> {

    @Override
    @SuppressWarnings("unchecked")
    public <R extends Number> R clean(R data, @NotNull Class<R> defineType, Round annotation) {
      if (annotation == null) throw new CleanException("未指定注解:" + Round.class);
      if (data == null) return null;

      BigDecimal value = data instanceof BigDecimal ? (BigDecimal) data : new BigDecimal(data.toString());
      value = value.setScale(annotation.value(), annotation.roundingMode());

      if (ReflectUtils.isAssignableFrom(defineType, BigDecimal.class)) return (R) value;
      if (ReflectUtils.isAssignableFrom(defineType, Float.class)) return (R) (Number) value.floatValue();
      if (ReflectUtils.isAssignableFrom(defineType, Double.class)) return (R) (Number) value.doubleValue();

      throw new CleanException("无法处理类型:" + defineType);
    }
  }
}
